home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / vmake / VMake.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-09  |  27.1 KB  |  832 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6. #include "vmake.h"
  7. #include "vmake_rev.h"
  8.  
  9. Prototype int CreateWindow(void);
  10. Prototype void DestroyWindow(void);
  11. Prototype char *SkipAss(const char *);
  12.  
  13. void myexit(void);
  14. int main(int, char **);
  15.  
  16. struct GLOBAL global;
  17. __aligned struct FileInfoBlock vmfib;
  18.  
  19. struct Library *GadToolsBase;
  20. struct Library *AslBase;
  21. struct Library *WorkbenchBase;
  22. struct Library *ArpBase;
  23.  
  24. char    *InitialFileName;
  25. char    *ConfigName;
  26. short   StartFromWB;
  27. short   BuildIt;
  28. char    *RexxScript;
  29. char    Buf[256];
  30.  
  31. #define TEMPLATE "PROJECT,REXX/K,CONFIG/K,BUILD/S"
  32.  
  33. ULONG oldSeconds, oldMicros; /* for double click filtering */
  34.  
  35. #define VM_PROJ        0
  36. #define VM_RSCRIPT     VM_PROJ+1
  37. #define VM_CONFIG      VM_RSCRIPT+1
  38. #define VM_BUILD       VM_CONFIG+1
  39. #define OPT_COUNT      VM_BUILD+1
  40.  
  41. long vm_opts[OPT_COUNT];
  42.  
  43. char *RexxHostName = "VMAKE" VERSTAG;
  44.  
  45. /***********************************************************************************
  46.  * Procedure: wbmain
  47.  * Synopsis:  rc = wbmain(WBStartup);
  48.  * Purpose:   Performs appropriate initialization to run program from Workbench
  49.  * Notes:     Parse tooltypes as a command.  Note that we are CD'd into the
  50.  *            application's directory, not the tooltype's icon's dir.
  51.  ***********************************************************************************/
  52. int wbmain(wbs)
  53. struct WBStartup *wbs;
  54. {
  55.    struct DiskObject *dob;
  56.    short i;
  57.    short j;
  58.    short FileSpecified = 0;
  59.    short abortIt = 0;
  60.  
  61.    /*
  62.     *  Search for options, set current directory to last valid
  63.     *  disk object.  Run commands specified by tool types in order
  64.     */
  65.  
  66.    for (i = 0; i < wbs->sm_NumArgs; ++i)
  67.    {
  68.       BPTR saveLock = CurrentDir((BPTR)wbs->sm_ArgList[i].wa_Lock);
  69.  
  70.       if (i == wbs->sm_NumArgs - 1 && FileSpecified == 0)
  71.       {
  72.          InitialFileName = strdup(wbs->sm_ArgList[i].wa_Name);
  73.       }
  74.  
  75.       if (dob = GetDiskObject(wbs->sm_ArgList[i].wa_Name))
  76.       {
  77.          if (dob->do_ToolTypes)
  78.          {
  79.             for (j = 0; dob->do_ToolTypes[j]; ++j)
  80.             {
  81.                char *ptr = dob->do_ToolTypes[j];
  82.  
  83.                if (strnicmp(ptr, "FILE=", 5) == 0)
  84.                {
  85.                   InitialFileName = strdup(SkipAss(ptr));
  86.                   FileSpecified = 1;
  87.                }
  88.                else
  89.                {
  90.                   if (strnicmp(ptr, "REXX=", 5) == 0)
  91.                   {
  92.                      RexxScript = strdup(SkipAss(ptr));
  93.                   }
  94.                   else
  95.                   {
  96.                      if (strnicmp(ptr, "CONFIG=", 7) == 0)
  97.                         ConfigName = strdup(SkipAss(ptr));
  98.                      else
  99.                      {
  100.                         if (strnicmp(ptr, "BUILD", 5) == 0)
  101.                            BuildIt = 1;
  102.                         else
  103.                         {
  104.                            /* These strings are needed for the requester      */
  105.                            global.text[TEXT_OK] = "OK";
  106.                            global.text[TEXT_CANCEL] = "Cancel";
  107.                            /* OK to use any text slot - will get overlaid     */
  108.                            global.text[1] = "Bad ToolType";
  109.                            /* Unfortunately the dos 1.3 version of request()  */
  110.                            /* dies of a contagious plague...                  */
  111.                            if ((DOSBase->dl_lib.lib_Version >= 36) &&
  112.                                !request(0, 1, ptr, NULL))
  113.                            {
  114.                               abortIt = 1;
  115.                               break;
  116.                            }
  117.                         }
  118.                      }
  119.                   }
  120.                }
  121.             }
  122.          }
  123.          FreeDiskObject(dob);
  124.       }
  125.       CurrentDir(saveLock);
  126.       if (abortIt)
  127.           break;
  128.    }
  129.  
  130.    if (abortIt == 0)
  131.    {
  132.       go_dir(wbs->sm_ArgList[wbs->sm_NumArgs-1].wa_Lock);
  133.       setup_cli();
  134.       StartFromWB = 1;
  135.       main(1, NULL);
  136.    }
  137. }
  138.  
  139. /***********************************************************************************
  140.  * Procedure: main
  141.  * Synopsis:  rc = main(argc, argv)
  142.  * Purpose:   The main entry point for the program
  143.  ***********************************************************************************/
  144. int main(int argc, char **argv)
  145. {
  146.    struct IntuiMessage *msg;
  147.    struct RDargs *rdargs;
  148.  
  149.    if (!StartFromWB)
  150.    {
  151.       if (DOSBase->dl_lib.lib_Version >= 36)
  152.       {
  153.          rdargs = ReadArgs(TEMPLATE, vm_opts, NULL);
  154.          if (rdargs == NULL)
  155.             PrintFault(IoErr(), NULL);
  156.          else
  157.          {           
  158.             InitialFileName = (char *)vm_opts[VM_PROJ];
  159.             RexxScript = (char *)vm_opts[VM_RSCRIPT];
  160.             ConfigName = (char *)vm_opts[VM_CONFIG];
  161.             BuildIt = vm_opts[VM_BUILD];
  162.          }
  163.       }
  164.       else
  165.       {
  166.          if (argc != 1)
  167.          {
  168.             InitialFileName = argv[1];
  169.          }
  170.       }
  171.    }
  172.  
  173.    /*
  174.     *   Open GadToolsBase/AslBase manually so we don't exit if they
  175.     *   don't exist.
  176.     */
  177.  
  178.    GadToolsBase  = OpenLibrary("gadtools.library", 0);
  179.    AslBase       = OpenLibrary("asl.library", 0);
  180.    WorkbenchBase = OpenLibrary("workbench.library", 0);
  181.  
  182.    memset(&global, 0, sizeof(global));
  183.  
  184.    if (AslBase != NULL)
  185.    /* Amigados version 2.0 or greater */
  186.    {
  187.       global.cbufsize = CBUF_SIZE_20; /* Long command lines */
  188.       global.freq = AllocFileRequest();
  189.    }
  190.    else
  191.    /* Amigados version 1.3 */
  192.    {
  193.       global.cbufsize = CBUF_SIZE_13; /* Short command lines */
  194.       ArpBase = OpenLibrary("arp.library", 0);
  195.       if (ArpBase != NULL)
  196.          global.freq = ArpAllocFreq();
  197.    }
  198.  
  199.    global.cbuf = malloc(global.cbufsize+1);
  200.    global.rexxrs = malloc(global.cbufsize+1);
  201.    if ((global.cbuf == NULL) || (global.rexxrs == NULL))
  202.       return(20); /* not enough memory to run & no good way to say why not */
  203.  
  204.    if (ConfigName)
  205.    {
  206.       global.parsefail = parse_config(ConfigName);
  207.       if (!global.parsefail)
  208.          Sym_Set(SYM_CONFIG, ConfigName, NULL);
  209.    }
  210.    else
  211.    {
  212.       global.parsefail = parse_config(ALT_CONFIG_FILE);
  213.       if (!global.parsefail)
  214.          Sym_Set(SYM_CONFIG, ALT_CONFIG_FILE, NULL);
  215.       else
  216.       {
  217.          if (global.parsefail == 2)
  218.          {
  219.             global.parsefail = parse_config(CONFIG_FILE);
  220.             if (!global.parsefail)
  221.                Sym_Set(SYM_CONFIG, CONFIG_FILE, NULL);
  222.          }
  223.       }
  224.    }
  225.  
  226.    if (!global.parsefail)
  227.       strcpy(global.title, global.text[TEXT_NOPROJ]);
  228.    Sym_Set(SYM_ORIG_CFG, Sym_Lookup(SYM_CONFIG), 0);
  229.  
  230.    {
  231.       /* We need to make the rexx port name available for them to use */
  232.       char *pname;
  233.       GetDiceRexxPortSlot(NULL, &pname);
  234.       if (pname != NULL)
  235.          Sym_Set(SYM_REXXPORT, pname, NULL);
  236.    }
  237.    /* REXX mode is initially non-interactive */
  238.    global.rexxinter = 0;
  239.    Sym_Set(SYM_REXXINTER, "OFF", NULL);
  240.  
  241. while (!global.done)
  242. {
  243.    /* global.screen is initialized to NULL to open on workbench screen */
  244.    /* stay in screen/window loop till reset by JUMP */
  245.    global.newscreen = 0;
  246.  
  247.    if(global.parsefail)
  248.    {
  249.       memset(global.menuitem, 0, sizeof(global.menuitem));
  250.       global.gadlist = NULL; /* doesn't happen when we freegadlist() */
  251.    }
  252.  
  253.    FillIn_RenderInfo(&global.ri, global.screen);
  254.  
  255.    /* Provide a default height/width so that we will get any errors displayed well */
  256.    global.width = global.ri.ScreenWidth-50;
  257.    global.height = global.ri.WindowTitle;
  258.  
  259.    global.ri.WindowTitle  += MARGIN_TOP;
  260.    global.ri.WindowLeft   += MARGIN_LEFT;
  261.    global.ri.WindowRight  += MARGIN_RIGHT + RESIZE_WIDTH;
  262.    global.ri.WindowBottom += MARGIN_BOTTOM;
  263.  
  264.    if (!global.parsefail)
  265.       if (!init_gad_sizes(global.ri.ScreenWidth, global.ri.ScreenHeight,0))
  266.       {
  267.          init_gadgets();
  268.       }
  269.  
  270.    if (!CreateWindow())
  271.    {
  272.       struct AppWindow *appwindow;
  273.       struct MsgPort *appmsgport;
  274.       struct AppMessage *appmsg;
  275.       long   waitflags = 1 << global.window->UserPort->mp_SigBit;
  276.  
  277.       if (WorkbenchBase && (WorkbenchBase->lib_Version >= 36))
  278.       {
  279.          if (appmsgport = CreateMsgPort())
  280.             appwindow = AddAppWindowA(
  281.                            1,     /* userID */
  282.                            0,     /* ptr to userdata, prototyped as long */
  283.                            global.window, appmsgport, /*obvious*/
  284.                            NULL   /* taglist */
  285.                         );
  286.          if (appwindow) waitflags |= 1 << appmsgport->mp_SigBit;
  287.       }
  288.       else
  289.       {
  290.          appwindow  = NULL;
  291.          appmsgport = NULL;
  292.       }
  293.  
  294.       waitflags |= 1 << RexxSigBit;
  295.  
  296.       set_gadgets(1);
  297.  
  298.       if (InitialFileName && !global.parsefail)
  299.       {
  300.          strcpy(global.filename, InitialFileName);
  301.          do_command("READ");
  302.       }
  303.  
  304.       /* ensure that console is available for REXX scripts etc. -- we're    */
  305.       /* either first time in or jumping to a new screen                    */
  306.       TermSession();
  307.       InitSession();
  308.  
  309.       if (RexxScript && !global.parsefail)
  310.       {
  311.          char buf[256];
  312.          sprintf(buf, "ADDR REXX %s %%(_PORT_) %s",
  313.                       RexxScript, global.filename);
  314.          do_command(buf);
  315.       }
  316.  
  317.       /* If there's no project loaded now, we need to ghost most menu items */
  318.       /* and cover the window so they can't play with the gadgets.          */
  319.       if ((global.filename[0] == 0) && !global.parsefail)
  320.       {
  321.          ghost_menus();
  322.          cover_window(); 
  323.       }
  324.       else   /* We have a project, do they want to build it right away?     */
  325.          if (BuildIt && !global.parsefail)
  326.             do_command(global.text[CONFIG_BUILD]);
  327.  
  328.       /* only use these on the first pass */ 
  329.       InitialFileName = RexxScript = NULL;
  330.       BuildIt = 0;
  331.  
  332.       while(!global.done  && !global.newscreen)
  333.       {
  334.          long mask;
  335.  
  336.          global.unghost = 0; /* will get set if we excute NEW or READ */
  337.  
  338.          mask = Wait(waitflags);
  339.          while(msg = (struct IntuiMessage *)GetMsg(global.window->UserPort))
  340.          {
  341.             ULONG class;
  342.             APTR iaddr;
  343.             USHORT code;
  344.             USHORT qual;
  345.             ULONG  Seconds, Micros;
  346.             struct XItem *xitem;
  347.  
  348.             code = msg->Code;
  349.             class = msg->Class;
  350.             iaddr = msg->IAddress;
  351.             qual  = msg->Qualifier;
  352.             Seconds = msg->Seconds;
  353.             Micros = msg->Micros;
  354.  
  355.             ReplyMsg((struct Message *)msg);
  356.  
  357.             switch(class)
  358.             {
  359.                case CLOSEWINDOW:
  360.                   do_command("QUIT");
  361.                   break;
  362.                case GADGETDOWN:
  363.                   /* We will only get this message from s list slider gadget  */
  364.                   /* but should really verify ... oh well                     */
  365.                   global.mouseprop = 1; /* streamline prop gadget handling    */
  366.                   ReportMouse(1, global.window);
  367.                   break;
  368.                case GADGETUP:
  369.                {
  370.                   int doubleclick;
  371.                   
  372. /* really want a reasonable way to initialize oldSecs/Micros for first call... */
  373.                   if (class == GADGETUP)
  374.                   {
  375.                      doubleclick = DoubleClick(oldSeconds, oldMicros,
  376.                                                Seconds, Micros);
  377.                      oldSeconds = Seconds;
  378.                      oldMicros = Micros;
  379.                   }
  380.                   handle_hit((struct Gadget *)iaddr,
  381.                       (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) ? 1 : 0,
  382.                       doubleclick);
  383.                   /* restore this after mouse dragging stops to avoid an      */
  384.                   /* extra screen flash.                                      */
  385.                   global.mouseprop = 0; /* do gadget hits from now on */
  386.                   ReportMouse(0, global.window);
  387.                   break;
  388.                }
  389.                case NEWSIZE:
  390.                   set_gadgets(0);
  391.                   free_gadlist(global.gadlist);
  392.                   init_gad_sizes(global.window->Width,
  393.                                  global.window->Height, 1);
  394.                   init_gadgets();
  395.                   SetBPen(global.rp, 0);
  396.                   SetAPen(global.rp, 0);
  397. /* debug - original
  398.                   RectFill( global.rp, global.ri.WindowLeft, global.ri.WindowTitle,
  399.                          global.window->Width  - global.ri.WindowRight + MARGIN_RIGHT - 1,
  400.                          global.window->Height - global.ri.WindowBottom + MARGIN_BOTTOM - 1);
  401. */
  402.                   RectFill( global.rp, global.ri.WindowLeft - MARGIN_LEFT,
  403.                          global.ri.WindowTitle,
  404.                          global.window->Width  - global.ri.WindowRight + MARGIN_RIGHT - 1,
  405.                          global.window->Height - global.ri.WindowBottom + MARGIN_BOTTOM - 1);
  406.                   set_gadgets(1);
  407.                   RefreshWindowFrame(global.window);
  408.                   break;
  409.                case MENUPICK:
  410.                   while (code != MENUNULL)
  411.                   {
  412.                      xitem = (struct XItem *)
  413.                              ItemAddress(global.menu, code);
  414.                      do_command(xitem->userdata);
  415.                      code = xitem->item.NextSelect;
  416.                   }
  417.                   break;
  418.                case VANILLAKEY:
  419. #ifdef DBG_JGM
  420.                   printf("Key:%d '%c'\n", code, code);
  421. switch (code)
  422. {
  423. case 'c':
  424.    mark_clean();
  425.    printf("set all objects clean\n");
  426.    break;
  427. case 'd':
  428.    {
  429.    int dirty;
  430.    dirty = test_dirty();
  431.    printf("Dirty state is %d\n", dirty);
  432.    break;
  433.    }
  434. case 'g':
  435.    ghost_menus();
  436.    break;
  437. case 'u':
  438.    unghost_menus();
  439.    break;
  440. }
  441. #endif
  442.  
  443.                   break;
  444.                case MOUSEMOVE:
  445.                   if (global.mouseprop == 1)
  446.                      handle_list(global.filelist, global.filelist->slider, 
  447.                                  CLASS_PROP, NULL, 0);
  448.                   break;
  449. /*
  450. default:
  451.    printf("Unknown IntuiMessage class %d\n", class);
  452.    break;
  453. */
  454.             }
  455.          }
  456.  
  457.          if (appwindow && global.filelist)
  458.          /* Must be Dos 2.0 or greater and must have list structure to put  */
  459.          /* file names into                                                 */
  460.          {
  461.             char appwinbuff[256];
  462.  
  463.             while (appmsg = (struct AppMessage *)GetMsg(appmsgport))
  464.             {
  465.                int i;
  466.                char *exttext = global.text[CONFIG_EXT];
  467.                int extlen = strlen(exttext);
  468.                int argnmln;
  469.                struct WBArg *argptr;
  470.                BYTE *argname;
  471.                char *projname; /* point to proj.DICE if found */
  472.  
  473.                argptr = appmsg->am_ArgList;
  474.                for (i = 0; i < appmsg->am_NumArgs; i++)
  475.                {
  476.                   int aproctype = 0;
  477.                   /* takes on values: 0  no defined processing           */
  478.                   /*                  1  add file name to list           */
  479.                   /*                  2  read in a project script        */
  480.                   /*                  3  go to dir - request script name */
  481.                   projname = NULL;
  482.                   argname = argptr->wa_Name;
  483.                   if (*argname) /* argument is a file, not a directory */
  484.                   {
  485.                      aproctype = 1; /* simple file */
  486.                      if ((argnmln = strlen(argname)) > extlen)
  487.                         if (!stricmp(argname + argnmln - extlen, exttext))
  488.                         {
  489.                            aproctype = 2; /* read project file */
  490.                            projname = (char *)argname;
  491.                         }
  492.                   }
  493.                   else /* directory - see if we can find a default project */
  494.                   {
  495.                      aproctype = 3; /* simple directory */
  496.                   }
  497.  
  498.                   if (aproctype >= 2) /* see if it's OK to change directory */
  499.                   {
  500.                      if (save_current(1) == 0)
  501.                      {
  502.                         BPTR dlock;
  503.                         go_dir(argptr->wa_Lock);
  504.                         if ((dlock = DupLock(argptr->wa_Lock)) != NULL)
  505.                         {
  506.                            UnLock(global.homedir);
  507.                            global.homedir = dlock;
  508.                         }
  509.                         else
  510.                            aproctype = 0; /* READ wouldn't work... */
  511.                      }
  512.                      else
  513.                         /* give up on this one */
  514.                         aproctype = 0;
  515.                   }
  516.  
  517.                   if (aproctype == 3) /* see if there is a default project */
  518.                   {
  519.                      if (Examine(argptr->wa_Lock, &vmfib))
  520.                      {
  521.                         BPTR dlock;
  522.                         strcpy(appwinbuff, vmfib.fib_FileName);
  523.                         strcat(appwinbuff, exttext);
  524.                         if (dlock = Lock(appwinbuff, SHARED_LOCK))
  525.                         {
  526.                            aproctype = 2; /* default project exists */
  527.                            projname = appwinbuff;
  528.                            UnLock(dlock);
  529.                         }
  530.                      }
  531.                   }
  532.  
  533.                   /* now we've figure out how to process the object - do it */
  534.                   switch (aproctype)
  535.                   {
  536.                      case 1: /* simple filename to add to list */
  537.              {
  538.                         int match = 0; /* directory match ? */
  539.                         int pdir = 0;  /* prepend directory name? */
  540.                         int l;
  541.                         char *p;
  542.                         BPTR fplock = 0, wplock =0;
  543.  
  544.                         if (SameLock(global.workdir, argptr->wa_Lock)
  545.                                == LOCK_SAME)
  546.                            match = 1;
  547.                         else
  548.                         {
  549.                            fplock = ParentDir(argptr->wa_Lock);
  550.                            if (SameLock(fplock, global.workdir)
  551.                                   == LOCK_SAME)
  552.                {
  553.                               match = 2;
  554.                               pdir = 1;
  555.                }
  556.                            else
  557.                            {
  558.                               wplock = ParentDir(global.workdir);
  559.                               if (SameLock(wplock, argptr->wa_Lock)
  560.                                      == LOCK_SAME)
  561.                                  match = 3;
  562.                               else
  563.                               {
  564.                                  if (SameLock(wplock, fplock)
  565.                         == LOCK_SAME)
  566.                  {
  567.                                     match = 4;
  568.                     pdir = 1;
  569.                  }
  570.                               }
  571.                            }
  572.                         }
  573.  
  574.                         *appwinbuff = '\0';
  575.                         if (match)
  576.                         /* Match   Filename
  577.                              0     <absolute path>/wa_Name
  578.                              1     wa_Name
  579.                              2     fparent/wa_Name
  580.                              3     /wa_Name
  581.                              4     /fparent/wa_Name
  582.                         */
  583.                         {
  584.                            if (match > 2)  /* 3 or 4 */
  585.                               strcpy(appwinbuff, "/");
  586.                            if (pdir)       /* parent dir name required */
  587.                            {
  588.                   if (Examine(argptr->wa_Lock, &vmfib))
  589.                   {
  590.                      strcat(appwinbuff, vmfib.fib_FileName);
  591.                                  /* note: fplock is valid when pdir = 1 */
  592.                      if (fplock == 0) /* name is root */
  593.                                     strcat(appwinbuff, ":");
  594.                   }
  595.                               else
  596.                                  match = 0;  /* no path name - forget it */
  597.                            }
  598.                         }
  599.             else
  600.                            if (NameFromLock(argptr->wa_Lock, appwinbuff, 255))
  601.                   pdir = 1;  /* have path in appwinbuff now */
  602.  
  603.                         /* path (if any) in appwinbuff, name in wa_Name */
  604.                         l = strlen(appwinbuff);
  605.                         p = appwinbuff+l;
  606.  
  607.                         if (pdir)  /* parent dir name in appwinbuff */
  608.             /* append "/" if approriate */
  609.                            if (*(p-1) != ':')
  610.                            {
  611.                               strcpy(p, "/");
  612.                               p++;
  613.                            }
  614.                         if (strlen(argptr->wa_Name) < (255-l))
  615.                            strcpy(p, argptr->wa_Name);
  616.                         handle_list(global.filelist, NULL, CLASS_ADD, appwinbuff, 0);
  617.  
  618.             if (fplock)
  619.                UnLock(fplock);
  620.             if (wplock)
  621.                UnLock(wplock);
  622.                         break;
  623.  
  624.              }
  625.                      case 2: /* project script: proj.DICE */
  626.                      {
  627.                         char cmdbuff[266];
  628.  
  629.                         strcpy(cmdbuff, "READ ");
  630.                         strcat(cmdbuff, projname);
  631.                         do_command(cmdbuff);
  632.                         break;
  633.                      }
  634.                      case 3: /* go to directory and prompt for file */
  635.                      {
  636.                         char cmdbuff[] = "READ ?";
  637.                         do_command(cmdbuff);
  638.                         break;
  639.                      }
  640.                   }
  641.                   argptr++;
  642.                }
  643.                ReplyMsg((struct Message *)appmsg);
  644.             }            
  645.          }
  646.  
  647.          /* See if they want us to do any rexx commands */
  648.          if (mask & (1 << RexxSigBit))
  649.             ProcessRexxCommands(NULL);
  650.  
  651.          /* we had to defer this because it messes up no end if you try to */
  652.          /* change the menus while processing a menupick intuimessage      */
  653.          if (global.unghost) /* set by Read or New commands */ 
  654.          {
  655.             if (global.filename[0]) /* Read or New might have failed... */
  656.             {  /* but they didn't */
  657.                unghost_menus();
  658.                uncover_window();
  659.             }
  660.             else
  661.             {  /* or else they did */
  662.                ghost_menus();
  663.                cover_window();
  664.             }
  665.          }
  666.       }
  667.       if (appwindow)  RemoveAppWindow(appwindow);
  668.       if (appmsgport) DeleteMsgPort(appmsgport);
  669.       set_gadgets(0);
  670.       free_gadlist(global.gadlist);
  671.       DestroyWindow();
  672.    }
  673.  
  674.    CleanUp_RenderInfo(&global.ri);
  675. /* this is where the open/close window loop ends */
  676.  
  677. }
  678.    UnLock(global.workdir);
  679.    UnLock(global.homedir);
  680.  
  681.    if (global.freq && (AslBase != NULL)) FreeFileRequest(global.freq);
  682.  
  683.    if (GadToolsBase  != NULL) CloseLibrary(GadToolsBase);
  684.    if (AslBase       != NULL) CloseLibrary(AslBase);
  685.    if (ArpBase       != NULL) CloseLibrary(ArpBase);
  686.    if (WorkbenchBase != NULL) CloseLibrary(WorkbenchBase);
  687.    return(0);
  688. }
  689.  
  690. /***********************************************************************************
  691.  * Procedure: CreateWindow
  692.  * Synopsis:  rc = CreateWindow();
  693.  * Purpose:   Create the window on the current screen using the current environment
  694.  ***********************************************************************************/
  695. int CreateWindow()
  696. {
  697.    struct NewWindow nw;
  698.  
  699.    struct TagItem    wintags[] = {
  700.       { WA_PubScreen,        (ULONG)global.screen },
  701.           /* The screen we want to be on */
  702.       { WA_PubScreenFallBack,    (ULONG)TRUE    }, /* Or workbench if not */
  703.       { TAG_DONE,        (ULONG)0    }
  704.    };
  705.  
  706.  
  707.    memset(&nw, 0, sizeof(nw));
  708.  
  709.    nw.Width      = global.width;
  710.    nw.Height     = global.height;
  711.    nw.LeftEdge   = (global.ri.ScreenWidth  - nw.Width ) / 2;
  712.    nw.TopEdge    = (global.ri.ScreenHeight - nw.Height) / 2;
  713.    nw.MinWidth   = 4*BUTTON_WIDTH;
  714.    nw.MinHeight  = 110;
  715.    nw.MaxWidth   = 0xffff;
  716.    nw.MaxHeight  = 0xffff;
  717.  
  718.    if ((nw.Width < 0) || (nw.Height < 0))
  719.       return(1);
  720.    nw.DetailPen  = nw.BlockPen = -1;
  721. if (global.parsefail)
  722. {
  723.    nw.IDCMPFlags = CLOSEWINDOW;
  724.    nw.Flags      = WINDOWDEPTH    |
  725.                    WINDOWCLOSE    |
  726.                    WINDOWDRAG     |
  727.                    SIMPLE_REFRESH |
  728.                    ACTIVATE       |
  729.                    NOCAREREFRESH;
  730.  
  731. }
  732. else
  733. {
  734.    nw.IDCMPFlags = GADGETUP    |
  735.                    GADGETDOWN  |
  736.                    MENUPICK    |
  737.                    MOUSEMOVE   |
  738.                    VANILLAKEY  |
  739.                    NEWSIZE     |
  740.                    CLOSEWINDOW;
  741.    nw.Flags      = WINDOWDEPTH    |
  742.                    WINDOWSIZING   |
  743.                    WINDOWCLOSE    |
  744.                    WINDOWDRAG     |
  745.                    SIMPLE_REFRESH |
  746.                    ACTIVATE       |
  747.                    NOCAREREFRESH;
  748.  
  749. }
  750.    nw.Title      = global.title;
  751.    if (AslBase != 0)  /* public screens come with Dos 2.0... */
  752.       {
  753.       nw.Type       = PUBLICSCREEN;
  754.  
  755.       global.window = OpenWindowTagList(&nw, wintags);
  756.       if (global.screen)
  757.          UnlockPubScreen(NULL, global.screen);
  758.       }
  759.    else /* do the Dos 1.3 version */
  760.       {
  761.       nw.Type       = WBENCHSCREEN;
  762.       global.window = OpenWindow(&nw);
  763.       }
  764.  
  765.    if (global.window == NULL) return(2);
  766.    SetWindowTitles(global.window, global.title, global.title2);
  767.    global.rp = global.window->RPort;
  768.    enable_menu();
  769.    return(0);
  770. }
  771.  
  772. /***********************************************************************************
  773.  * Procedure: DestroyWindow
  774.  * Synopsis:  (void)DestroyWindow();
  775.  * Purpose:   Make the current window go away
  776.  ***********************************************************************************/
  777. void DestroyWindow()
  778. {
  779.    free_menus(global.menu);
  780.    CloseWindow(global.window);
  781. global.window = 0; /* do we need this? */
  782. }
  783.  
  784.  
  785. /***********************************************************************************
  786.  * Procedure: SkipAss
  787.  * Synopsis:  p = SkipAss(ptr)
  788.  * Purpose:   Skip whitespace in tooltype assignment
  789.  ***********************************************************************************/
  790. char * SkipAss(const char *ptr)
  791. {
  792.    while (*ptr && *ptr != '=')
  793.       ptr++;
  794.    if (*ptr == '=')
  795.    {
  796.       for (ptr++; *ptr == ' ' || *ptr == '\t'; ptr++)
  797.          ;
  798.    }
  799.    return(ptr);
  800. }
  801.  
  802. /***********************************************************************************
  803.  * Procedure: DoRexxCommand
  804.  * Synopsis:  rc = DoRexxCommand(msg, port, arg, pres)
  805.  * Purpose:   Handling executing a rexx command
  806.  ***********************************************************************************/
  807. long DoRexxCommand(void *msg,              /* RexxMsg structure if we need it      */
  808.                    struct MsgPort *port,   /* MsgPort structure if we need it      */
  809.                    char *arg0,             /* arg0                                 */
  810.                    char **pres             /* where to put our result if rc==0     */
  811.                   )
  812. {
  813.    if (!global.rexxinter)
  814.       global.inrexx = 1;      /* controls some error processing         */
  815.    global.rexxmsgs = 1;       /* always get messages & return codes     */
  816.    global.rexxrs[0] = '\0';   /* clear any leftover value               */
  817.    global.rexxrc = 0;         /* presumed innocent until proven guilty  */
  818.    InitSession();             /* ensure console window will be around   */
  819.  
  820. strcpy(global.rexxrs, "Command OK");
  821.    do_command(arg0);
  822.  
  823.    global.rexxmsgs = 0;
  824.    global.inrexx = 0;         /* revert to non-rexx error handling      */
  825.    if (global.rexxrc == 0)
  826.       *pres = global.rexxrs;  /* result string (might point to "")      */
  827.    else
  828.       global.rexxrc += 1;     /* to match numbering in documentation    */
  829.    return(global.rexxrc);
  830. }
  831.  
  832.